﻿ using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Json;
using System.Collections;
using System.Web;
using System.Data;
using System.Dynamic;
using FluorineFx.Json;
using System.Reflection;

namespace lxwmvc
{
    /// <summary>
    /// 两边关联
    /// </summary>
    internal enum guanlian
    {
        /// <summary>
        /// 
        /// </summary>
        inner_join,
        /// <summary>
        /// 
        /// </summary>
        left_join,
        /// <summary>
        /// 
        /// </summary>
        right_join,
        /// <summary>
        /// 
        /// </summary>
        full_join,
        /// <summary>
        /// 
        /// </summary>
        empty
    }

    /// <summary>
    /// 存储关联类型
    /// </summary>
    internal class ti
    {
        /// <summary>
        /// 
        /// </summary>
        public guanlian guanlian { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string on { get; set; }
    }

 
    /// <summary>
    /// 通用实体类
    /// </summary>
    public class supermodel : DynamicObject
    {
        /// <summary>
        /// 实体类初始化
        /// </summary>
        /// <param name="tablename"></param>
        public supermodel(string tablename = "")
        {
            if (!string.IsNullOrEmpty(tablename)) table(tablename);
        }

        /// <summary>
        /// 实体类初始化
        /// </summary>
        public supermodel()
        {
        }

        /// <summary>
        /// 初始化
        /// </summary>
        static supermodel()
        {
            //如果不存在，重新捕获
            if (systableinfo == null || systableinfo.Rows.Count == 0 || pks == null || pks.Count == 0)
            {
                var sql = @"SELECT 
(case when a.colorder=1 then d.name else '' end) N'tablename',
lower(a.name) N'column',
(case when COLUMNPROPERTY( a.id,a.name,'IsIdentity')=1 then '1'else '0' end) N'pk',
b.name N'type',
a.length N'len',
(case when a.isnullable=1 then '1'else '0' end) N'null'
FROM  syscolumns  a left join systypes b 
on  a.xtype=b.xusertype
inner join sysobjects d 
on a.id=d.id  and  d.xtype='U' and  d.name<>'dtproperties'
left join syscomments e
on a.cdefault=e.id
order by object_name(a.id),a.colorder";
                //加载外部页面
                try
                {
                    //获取数据库相关信息
                    systableinfo = sqlhelper.out_getds(sql).Tables[0];

                    string tablename = "";
                    for (int i = 0; i < systableinfo.Rows.Count; i++)
                    {
                        if (systableinfo.Rows[i]["tablename"].tostr().Length > 0)
                        {
                            tablename = systableinfo.Rows[i]["tablename"].tostr();
                        }
                        else
                        {
                            //赋值，把没有信息的补全
                            systableinfo.Rows[i]["tablename"] = tablename;
                        }

                        if (systableinfo.Rows[i]["pk"].tostr() == "1")
                        {
                            //得到表的递增列
                            pks[tablename] = systableinfo.Rows[i]["column"].tostr();
                        }
                    }
                }
                catch { }
            }
        }

        Dictionary<string, ti> tablelist = new Dictionary<string, ti>(StringComparer.OrdinalIgnoreCase);
        Dictionary<string, object> setlist = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);

        string _where = "";
        string _orderby = "";
        string _pk = "";
        string _select = "*";

        /// <summary>
        /// 得到系统表结构
        /// </summary>
        static DataTable systableinfo = null;
        /// <summary>
        /// 表的主键值
        /// </summary>
        public static Dictionary<string, string> pks = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
        
        /// <summary>
        /// 初始化表结构
        /// </summary>
        DataTable tableinfo
        {
            get
            {
                return systableinfo;
            }
        }
        /// <summary>
        /// 初始化并返回model
        /// </summary>
        /// <returns></returns>
        public static supermodel create(string tablename = "")
        {
            return new supermodel(tablename);
        }

        Dictionary<string, object> dictionary
            = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);

        /// <summary>
        /// 容器内部数量
        /// </summary>
        public int Count
        {
            get
            {
                return dictionary.Count;
            }
        }

        /// <summary>
        /// 检查对应的key是否存在
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool ContainsKey(string key)
        {
            key = key.ToLower();
            return dictionary.ContainsKey(key);
        }

        /// <summary>
        /// 检查对应的key是否存在
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool Contains(string key)
        {
            key = key.ToLower();
            return dictionary.ContainsKey(key);
        }

        /// <summary>
        /// CRUD操作之前如果没有设置table，会出现错误
        /// </summary>
        /// <param name="tablename"></param>
        /// <returns></returns>
        public supermodel table(string tablename)
        {
            tablename = tablename.ToLower();

            ifnullerror(tablename, tablename + "表名不允许为空!");
            //var first = tablelist.Where(o => o.Value.guanlian == guanlian.empty).First<ti>();

            try
            {
                var first = tablelist.Where(o => o.Value.guanlian == guanlian.empty).First();
                this.tablelist.Remove(first.Key);
            }
            catch { }

            this.tablelist[tablename] = new ti() { guanlian = guanlian.empty, on = "" };
            ifnullerror(tableinfo.Select(" tablename='" + tablename + "'").Length == 0 ? "" : " ", tablename + "表在系统中不存在!");

            //得到真实的表
            if (!pks.ContainsKey(tablename))
            {
                throw new Exception(tablename + "此表没有递增主键!");
            }

            this._pk = pks[tablename];
            return this;
        }

        /// <summary>
        /// 返回主键
        /// </summary>
        string PK
        {
            get
            {
                ifnullerror(_pk, "此表为设置递增主键");
                return _pk;
            }
        }

        /// <summary>
        /// set name=xxxx，主要用于update
        /// </summary>
        /// <param name="k"></param>
        /// <param name="v"></param>
        /// <returns></returns>
        public supermodel set(string k, object v)
        {
            k = k.ToLower();
            setlist[k] = v;
            this[k] = v;
            return this;
        }

        /// <summary>
        /// 插入对象
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public object this[string key]
        {
            get
            {
                if (dictionary.ContainsKey(key))
                    return dictionary[key]??"";
                //防止出现错误
                return "";
            }
            set
            {
                dictionary[key] = Convert.IsDBNull(value) ? null : value;
            }
        }
        /// <summary>
        /// 内部用
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        object _o(string key)
        {
            if (dictionary.ContainsKey(key))
                return dictionary[key];
            return null;
        }

        ///// <summary>
        ///// 内部用
        ///// </summary>
        ///// <param name="key"></param>
        ///// <param name="value"></param>
        //void _add(string key, object value)
        //{
        //    this[key] = value;
        //}

        ///// <summary>
        ///// 输出page信息
        ///// </summary>
        ///// <param name="pb"></param>
        ///// <returns></returns>
        //public pageinfo pager(pagebase pb)
        //{
        //    StringBuilder sb = new StringBuilder();
        //    foreach (var o in tablelist)
        //    {
        //        sb.Append(" ");
        //        if (o.Value.guanlian != guanlian.empty)
        //        {
        //            if (o.Value.guanlian == guanlian.inner_join)
        //                sb.Append(" inner join ");
        //            else if (o.Value.guanlian == guanlian.left_join)
        //                sb.Append(" left join ");
        //            else if (o.Value.guanlian == guanlian.right_join)
        //                sb.Append(" right join ");
        //            else if (o.Value.guanlian == guanlian.full_join)
        //                sb.Append(" full join ");
        //            sb.Append(o.Key);
        //            sb.Append(" ");
        //            sb.Append(o.Value.on);
        //        }
        //        else
        //        {
        //            sb.Append(o.Key);
        //        }
        //    }

        //    //只有分页特殊一点。
        //    string w = pb.search(_where);

        //    string paixu = "";
        //    string strValue = requesthelper.getonevalue("cn");
        //    if (!string.IsNullOrEmpty(strValue) || string.IsNullOrEmpty(_orderby))
        //    {
        //        paixu = pb.orderbycolumn(_pk, pb.ordertype("desc"));
        //    }
        //    else
        //    {
        //        paixu = _orderby;
        //    }

        //    return sqlhelper.showpager(pb, sb.tostr(), _select, paixu, pb.page, pb.pagesize, w);
        //}

        /// <summary>
        /// 选择的列,如果为空，默认为*
        /// </summary>
        /// <param name="k"></param>
        /// <returns></returns>
        public supermodel select(string k = "")
        {
            if (string.IsNullOrEmpty(k))
                _select = "*";
            else
                _select = k;

            return this;
        }
        /// <summary>
        /// 传递where，例如： name='xx'
        /// </summary>
        /// <param name="w"></param>
        /// <returns></returns>
        public supermodel where(string w)
        {
            _where = w;
            return this;
        }


        /// <summary>
        /// 获取Keys集合
        /// </summary>
        public Dictionary<string, object>.KeyCollection Keys
        {
            get
            {
                return dictionary.Keys;
            }
        }

        /// <summary>
        /// 获取Values集合
        /// </summary>
        public Dictionary<string, object>.ValueCollection Values
        {
            get
            {
                return dictionary.Values;
            }
        }

        /// <summary>
        /// 得到
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="index"></param>
        /// <returns></returns>
        public T Value<T>(int index)
        {
            if(dictionary.Values.Count == 0)
                return default(T);

            return dictionary.Values.ElementAt(index).toT<T>();
        }

        /// <summary>
        /// 传递group，例如：name
        /// </summary>
        /// <param name="w"></param>
        /// <returns></returns>
        public supermodel group(string w)
        {
            _groupby = w;
            return this;
        }

        /// <summary>
        /// 排序order,例如 name desc,age asc
        /// </summary>
        /// <param name="o"></param>
        /// <returns></returns>
        public supermodel orderby(string o)
        {
            _orderby = o;
            return this;
        }

        string _tablename
        {
            get
            {
                try
                {
                    string tablename = (from o in tablelist where o.Value.guanlian == guanlian.empty select o).First().Key;
                    return tablename.Split(' ')[0];//防止出现错误
                }
                catch { }

                ifnullerror("", "未设置table名!");
                return "";
            }
        }

        /// <summary>
        /// 删除对象,flag=true 代表有没有where都可以执行delete。
        /// </summary>
        public int delete(bool flag = false)
        {
            //删除记录
            string tablename = _tablename;
            ifnullerror(tablename, "未设置table名!");
            string sql = "delete from [{0}] where {1}";

            string w = _where;
            if (string.IsNullOrEmpty(w) && flag)
            {
                if (this.ContainsKey(PK) && this[PK].tostr()!="")
                    w = " " + PK + "=" + this[PK];
            }
            ifnullerror(w, "未设置where条件，没有请设置1=1");

            //执行删除命令
            return queryhelper.execute(string.Format(sql, tablename, w));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="_where"></param>
        /// <param name="flag"></param>
        /// <returns></returns>
        public T select<T>(string _where = "", bool flag = true)
        {
            //删除记录
            string tablename = _tablename;
            ifnullerror(tablename, "未设置table名!");
            string sql = "select top 1 * from [{0}] where {1}";

            string w = _where;
            if (string.IsNullOrEmpty(w) && flag)
            {
                if (this.ContainsKey(PK) && this[PK].tostr() != "")
                    w = " " + PK + "=" + this[PK];
            }
            ifnullerror(w, "未设置where条件，没有请设置1=1");

            //执行删除命令
            return queryhelper.get<T>(string.Format(sql, tablename, w));
        }

        void ifnullerror(string tablename, string p)
        {
            if (string.IsNullOrEmpty(tablename)) throw new Exception(p);
        }

        /// <summary>
        /// 对象更新,flag=true 代表有没有where条件用主键代替。
        /// </summary>
        public int update(bool flag = false)
        {
            string tablename = _tablename;
            ifnullerror(tablename, "未设置table名!");
            string sql = "update [{0}] set {1} where {2}";

            Dictionary<string, object> param = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
            string set = "";
            foreach (var o in setlist)
            {
                DataRow[] drs = tableinfo.Select(" tablename='" + tablename + "' and column='" + o.Key + "'");
                if (drs == null || drs.Length == 0) continue;
                //主键不要更新
                if (o.Key.Equals(PK, StringComparison.OrdinalIgnoreCase)) continue;

                string type = drs[0]["type"].tostr().ToLower();
                string _null = drs[0]["null"].tostr();

                param[o.Key] = o.Value;
                set += "," + o.Key + "=@" + o.Key;

                //设置为空
                if (_null == "1" && o.Value == null) continue;

                switch (type)
                {
                    case "int":
                        {
                            if (o.Value != null)
                            {
                                try
                                {
                                    param[o.Key] = null;
                                    param[o.Key] = o.Value.toint32(0, true);
                                }
                                catch { }
                            }
                            break;
                        }
                    case "decimal":
                        {
                            if (o.Value != null)
                            {
                                try
                                {
                                    param[o.Key] = null;
                                    param[o.Key] = o.Value.todecimal(0,true);
                                }
                                catch { }
                            }
                            break;
                        }
                    case "datetime":
                        {
                            try
                            {
                                param[o.Key] = null;
                                if (o.Value != null) param[o.Key] = o.Value.todatetime("", true) + "";
                            }
                            catch { }
                            break;
                        }
                }
            }

            string w = _where;
            if (string.IsNullOrEmpty(w) && flag)
            {
                if (this.ContainsKey(PK) && this[PK].tostr() != "")
                    w = " " + PK + "=" + this[PK];
            }
            ifnullerror(w, "未设置where条件，没有请设置1=1");

            if (set.Length > 0) set = set.Substring(1);
            else return 0;

            //执行更新命令
            return queryhelper.execute(string.Format(sql, tablename, set, w), param);
        }

        /// <summary>
        /// 得到一个supermodel，如果不存在，默认为null
        /// </summary>
        /// <returns></returns>
        public supermodel get()
        {
            string sql = createselect();
            supermodel model = queryhelper.get<supermodel>(sql);
            
            if (model == null) 
                return null;

            foreach (string s in model.Keys)
            {
                this[s] = model[s];
            }
            return this;
        }

        /// <summary>
        /// 获取实体对象或者第一行第一列的对象  相当于one[T]
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T get<T>()// where T:supermodel,new()
        {
            string sql = createselect();
            return queryhelper.get<T>(sql);
        }

        /// <summary>
        /// 返回List T
        /// </summary>
        /// <returns></returns>
        public IEnumerable<T> list<T>(int top = 0) where T:supermodel,new()
        {
            string sql = createselect(top);
            return queryhelper.query<T>(sql);
        }
        /// <summary>
        /// 返回List supermodel
        /// </summary>
        /// <param name="top"></param>
        /// <returns></returns>
        public IEnumerable<supermodel> list(int top = 0)
        {
            return list<supermodel>(top);
        }
        /// <summary>
        /// 返回一种类型
        /// </summary>
        /// <typeparam name="T">返回的类型</typeparam>
        /// <returns>返回指定类型的对象</returns>
        public T one<T>()
        {
            string sql = createselect();
            return queryhelper.get<T>(sql);

            //http://www.cnblogs.com/Ninputer/
            //http://www.cnblogs.com/JeffreyZhao/archive/2009/03/10/codetimer.html
            
            //var random = new Random(DateTime.Now.Millisecond);
            //var array = Enumerable.Repeat(0, 1000 * 500).Select(_ => random.Next()).ToArray();
        }

        /// <summary>
        /// 生成sql语句
        /// </summary>
        /// <param name="top"></param>
        /// <returns></returns>
        string createselect(int top = 1)
        {
            string tablename = _tablename;
            ifnullerror(tablename, "未设置table名!");

            StringBuilder sb = new StringBuilder();
            sb.Append(" select ");
            sb.Append(" ");
            if (top > 0) sb.Append("top " + top);
            sb.Append(" ");
            sb.Append(_select);
            sb.Append(" ");
            sb.Append(" from ");
            foreach (var o in tablelist)
            {
                sb.Append(" ");
                if (o.Value.guanlian != guanlian.empty)
                {
                    if (o.Value.guanlian == guanlian.inner_join)
                        sb.Append(" inner join ");
                    else if (o.Value.guanlian == guanlian.left_join)
                        sb.Append(" left join ");
                    else if (o.Value.guanlian == guanlian.right_join)
                        sb.Append(" right join ");
                    else if (o.Value.guanlian == guanlian.full_join)
                        sb.Append(" full join ");
                    sb.Append(o.Key);
                    sb.Append(" on ");
                    sb.Append(o.Value.on);
                }
                else
                {
                    sb.Append(o.Key);
                }
            }
            sb.Append(" ");
            sb.Append("where ");
            string w = _where;
            if (string.IsNullOrEmpty(w)) w = " 1=1 ";
            sb.Append(w);

            if (!string.IsNullOrEmpty(_groupby))
                sb.Append(" group by " + _groupby);

            //排序字段
            if (!string.IsNullOrEmpty(_orderby))
                sb.Append(" order by " + _orderby);

            return sb.tostr();
        }



        /// <summary>
        /// 插入队列
        /// </summary>
        /// <param name="key"></param>
        /// <param name="v"></param>
        /// <returns></returns>
        public supermodel add(string key, object v)
        {
            this[key.ToLower().Trim()] = v;
            return this;
        }

        /// <summary>
        /// 把后面的数据追加到前面
        /// </summary>
        /// <param name="dizhi"></param>
        public void add(supermodel dizhi)
        {
            foreach (string k in dizhi.Keys)
                this[k] = dizhi[k];
        }

        /// <summary>
        /// 实体的操作
        /// </summary>
        /// <param name="_insert"></param>
        /// <param name="_update"></param>
        /// <returns></returns>
        public result saveorupdate(Action<supermodel> _insert = null, Action<supermodel> _update = null)
        {
            string tablename = _tablename;
            ifnullerror(tablename, "未设置table名!");
            result result = new lxwmvc.result();

            //得到主键对应的内容
            int keyValue = _o(PK).toint32(-1);

            result.action = keyValue > 0 ? action.update : action.insert;

            //如果主键在系统中不存在，就不要执行更新操作
            if (result.action == action.update)
            {
                //如果数据库里面不存在?
                var sqlCount = "select count(1) from "+tablename+" where "+PK+"=@0";
                result.action = queryhelper.get<int>(sqlCount, keyValue) > 0?
                    action.update : action.insert;
            }

            //给一些未赋值的变量赋值
            if (result.action == action.update)
            {
                if (_update != null) _update(this);
            }
            else
            {
                //动态赋值
                string keys = requesthelper.getonevalue("_lxw_column_keys_").tostr();
                string defaultvalue = requesthelper.getonevalue("_lxw_column_default_value_").tostr();
                string checkboxs = requesthelper.getonevalue("_lxw_column_checkbox_").tostr();
                string datetimes = requesthelper.getonevalue("_lxw_column_datetime_").tostr();

                if (keys.Length > 0)
                {
                    foreach (string s0 in keys.Split(','))
                    {
                        //去掉前面的_
                        if (string.IsNullOrEmpty(s0)) continue;
                        string s = s0.TrimStart(new char[] { '_' });

                        if (stringhelper.findvalue(checkboxs, s0))
                        {
                            this[s] = this[s].tostr() == "on" ? 1 : 0;
                            continue;
                        }

                        if (stringhelper.findvalue(datetimes, s0))
                        {
                            this[s] = DateTime.Now;
                            continue;
                        }
                        //赋值
                        this[s] = requesthelper.fromurlparamsgetvaluebykey(defaultvalue, s0);
                    }
                }
                if (_insert != null) _insert(this);
            }
            return _(tablename, result);
        }

        result _(string tablename, result result)
        {
            result.model = this;

            string updateColumns = "";
            string insertColumns = "";
            string insertValues = "";

            Dictionary<String, object> param = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
            DataRow[] drs = tableinfo.Select(" tablename='" + tablename + "'");
            foreach (DataRow d in drs)
            {
                string _column = d["column"].tostr();
                string _null  = d["null"].tostr();
                string _type  = d["type"].tostr().ToLower();
                //主键不要更新，insert 或者 update 都不要更新
                if (_column.Equals(_pk, StringComparison.OrdinalIgnoreCase)) continue;
                
                //这里比较特殊 20120610，主要是有些字段是乱七八糟的。
                if (_column.IndexOf('=') != -1) continue;
                
                //允许为空，并且集合中不存在
                if (_null == "1" && !this.ContainsKey(_column)) continue;
                
                //也有设置为空的时候，专门设置为空
                //if (_null == "1" && this.ContainsKey(column) && this[column] == null) continue;

                //20121023 lxw
                //这句话非常好，只更新传递的值，其他值不更新
                if (result.action == action.update && !this.ContainsKey(_column)) continue;

                insertColumns += "," + _column + "";
                updateColumns += "," + _column + "=";

                insertValues += ",@" + _column;
                updateColumns += "@" + _column;


                if (_null == "1" && _o(_column) == null)
                {
                    //专门设置为空
                    param[_column] = null;
                    continue;
                }

                if (_type == "int") {
                    try
                    {
                        param[_column] = null;
                        param[_column] = this[_column].toint32(0, true);
                    }
                    catch { }
                }
                else if (_type == "decimal")
                {
                    try
                    {
                        param[_column] = null;
                        param[_column] = this[_column].todecimal(0, true);
                    }
                    catch { }
                }
                else if (_type == "datetime")
                {
                    try
                    {
                        //默认日期
                        param[_column] = null;
                        param[_column] = this[_column].todatetime("1900-1-1", true);
                    }
                    catch { }
                }
                else param[_column] = this[_column];
            }
            string updateSql = "update {0} set {1} where {2}={3}";
            string InsertSql = "insert into {0}({1}) values({2});select @@identity";


            if (result.action == action.update)
            {
                //这里修改过错误
                var ret = queryhelper.execute(string.Format(updateSql, tablename, updateColumns.TrimStart(','), _pk, this[_pk]), param);
                //如果是什么都没有，返回-1，代表更新或者插入失败
                result.identity = ret>0?this[_pk].toint32(0):-1;
            }
            else
            {
                result.identity = queryhelper.get<int>(
                    string.Format(InsertSql, tablename, 
                    insertColumns.TrimStart(','), 
                    insertValues.TrimStart(',')),
                    param);
                //插入主键
                result.model[PK] = result.identity;
            }

            return result;
        }


        /// <summary>
        /// inner
        /// </summary>
        /// <param name="tablename"></param>
        /// <param name="on"></param>
        /// <returns></returns>
        public supermodel inner(string tablename, string on)
        {
            tablename = tablename.ToLower();
            tablelist[tablename] = new ti() { guanlian = guanlian.inner_join, on = on };
            return this;
        }
        /// <summary>
        /// left
        /// </summary>
        /// <param name="tablename"></param>
        /// <param name="on"></param>
        /// <returns></returns>
        public supermodel left(string tablename, string on)
        {
            tablename = tablename.ToLower();
            tablelist[tablename] = new ti() { guanlian = guanlian.left_join, on = on };
            return this;
        }
        /// <summary>
        /// right
        /// </summary>
        /// <param name="tablename"></param>
        /// <param name="on"></param>
        /// <returns></returns>
        public supermodel right(string tablename, string on)
        {
            tablename = tablename.ToLower();
            tablelist[tablename] = new ti() { guanlian = guanlian.right_join, on = on };
            return this;
        }

        /// <summary>
        /// full
        /// </summary>
        /// <param name="tablename"></param>
        /// <param name="on"></param>
        /// <returns></returns>
        public supermodel full(string tablename, string on)
        {
            tablename = tablename.ToLower();
            tablelist[tablename] = new ti() { guanlian = guanlian.full_join, on = on };
            return this;
        }
        string _groupby = "";


        /// <summary>
        /// 从队列里面移除
        /// </summary>
        /// <param name="key"></param>
        public void remove(string key)
        {
            if (dictionary.ContainsKey(key))
                dictionary.Remove(key);
        }

        /// <summary>
        /// 从队列里面移除所有的
        /// </summary>
        public void removeall()
        {
            dictionary.Clear();
        }

        /// <summary>
        /// 外部不允许访问
        /// </summary>
        /// <param name="binder"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        public override bool TryGetMember(
            GetMemberBinder binder, out object result)
        {
            string name = binder.Name.ToLower();
            if (!dictionary.ContainsKey(name))
            {
                //防止出错
                result = "";
                return true;
            }
            return dictionary.TryGetValue(name, out result);
        }

        /// <summary>
        /// 从队列里面得到正确类型的数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public T get<T>(string key)
        {
            string name = key.ToLower();
            if (!dictionary.ContainsKey(name))
            {
                return default(T);
            }
            object obj = null;
            dictionary.TryGetValue(name, out obj);

            //这个地方返回null好
            if (obj == null) return default(T);

            Type t = typeof(T);
            if (t == typeof(int))
                return (T)Convert.ChangeType(obj.toint32(), t);            
            else if (t == typeof(decimal))
                return (T)Convert.ChangeType(obj.todecimal(), t);
            else if (t == typeof(string))
                return (T)Convert.ChangeType(obj.tostr(), t);
            else if (t == typeof(DateTime))
                return (T)Convert.ChangeType(obj.todatetime(), t);

            //http://www.csharpwin.com/csharpspace/12851r5551.shtml
            if (!typeof(T).IsGenericType) { 
                return (T)Convert.ChangeType(obj, typeof(T)); 
            }
            Type genericTypeDefinition = typeof(T).GetGenericTypeDefinition(); 
            if (genericTypeDefinition == typeof(Nullable<>)) {
                if(obj== null || obj.tostr() == "") return default(T);
                return (T)Convert.ChangeType(obj, Nullable.GetUnderlyingType(typeof(T)));
            }


            throw new InvalidCastException(string.Format("无效的类型转换 \"{0}\" to type \"{1}\".",
                obj.GetType().FullName, 
                typeof(T).FullName));
        }

        static bool IsNullableType(Type theType)
        {
            return (theType.IsGenericType && theType.
              GetGenericTypeDefinition().Equals
              (typeof(Nullable<>)));
        }

        /// <summary>
        /// TrySetMember 外部不允许调用
        /// </summary>
        /// <param name="binder"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public override bool TrySetMember(
            SetMemberBinder binder, object value)
        {
            dictionary[binder.Name.ToLower()] = value;
            return true;
        }

        /// <summary>
        /// 输出json字符串
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            if (Count > 0)
                return JavaScriptConvert.SerializeObject(this.tojson());
            else
                return createselect();            
        }

        /// <summary>
        /// 转换成model
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T toModel<T>()
        {
            var t = typeof(T);
            var obj = Activator.CreateInstance(t);


            //下面的实体比较特殊
            if (t.IsSubclassOf(typeof(supermodel)))
            {
                var model = (supermodel)obj;
                foreach (string key in this.Keys)
                {
                    try
                    {
                        model[key] = this[key];
                    }
                    catch { }
                }

                return (T)(model as object);
            }

            //普通实体，用反射赋值，以后可以修改成IL赋值方法
            foreach (string key in this.Keys)
            {
                try
                {
                    var p = t.GetProperty(key, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.IgnoreCase);
                    if (p == null) continue;

                    var v = this[key] == DBNull.Value ? "" : (this[key] ?? "");
                    if (p.PropertyType == typeof(int)) p.SetValue(obj, v.toint32(0, true), null);
                    if (p.PropertyType == typeof(DateTime)) p.SetValue(obj, v.todatetime("", true), null);
                    if (p.PropertyType == typeof(decimal)) p.SetValue(obj, v.todecimal(0, true), null);
                    if (p.PropertyType == typeof(string)) p.SetValue(obj, v, null);
                }
                catch { }
            }


            return (T)obj;
        }

        /// <summary>
        /// 通过实体转换成supermodel
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public supermodel fromModel(object obj)
        {
            var t = obj.GetType();
            var ps = t.GetProperties(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.IgnoreCase);
            var psF = t.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.IgnoreCase);

            var tns = t.tostr().Split('.');

            try
            {
                //设置tablename
                table(tns[tns.Length - 1]);
            }
            catch { }

            foreach (PropertyInfo p in ps)
            {
                try
                {
                    this[p.Name.ToLower()] = p.GetValue(obj, null);
                }
                catch { }
            }
            foreach (FieldInfo p in psF)
            {
                try
                {
                    this[p.Name.ToLower()] = p.GetValue(obj);
                }
                catch { }
            }
            return this;
        }


        /// <summary>
        /// 复制对象，只复制对象里面的内容，内部关系不复制,用处是否存在？
        /// </summary>
        /// <param name="flag">true:不保留主键</param>
        /// <returns></returns>
        public supermodel clone(bool flag = true)
        {
            var tbn = "";
            var pk = "";
            try
            {
                tbn = this._tablename;
                pk = this.PK;
            }
            catch { }
            var model = supermodel.create(tbn);
            //这里存在问题，如果key里面存储的是应用类型的，可能会带来问题。
            foreach (string key in this.Keys) model[key] = this[key];
            if (pk != "" && flag == false) model.remove(pk);
            return model;
        }

        /// <summary>
        /// 只返回有主键的对象
        /// </summary>
        /// <returns></returns>
        public supermodel clear()
        {
            var pkv = this[PK];
            this.removeall();
            this[PK] = pkv;

            return this;
        }

        /// <summary>
        /// 隐式转换，把hashtable转成supermodel
        /// </summary>
        /// <param name="has"></param>
        /// <returns></returns>
        public static implicit operator supermodel(Hashtable has)
        {
            supermodel sm = supermodel.create();
            foreach (string key in has.Keys)
                sm[key.ToLower()] = has[key];

            return sm;
        }

        /// <summary>
        /// 隐式转换，把JavaScriptObject转成supermodel
        /// </summary>
        /// <param name="jso"></param>
        /// <returns></returns>
        public static implicit operator supermodel(JavaScriptObject jso)
        {
            supermodel sm = supermodel.create();
            foreach (string key in jso.Keys)
                sm[key.ToLower()] = jso[key];

            return sm;
        }

        //public static implicit operator T(supermodel has)
        //{
        //    var t = typeof(T);
        //    var obj = t.Assembly.CreateInstance(t.FullName);
        //    foreach (string key in has.Keys)
        //    {
        //        try
        //        {
        //            var p = t.GetProperty(key, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.IgnoreCase);
        //            if (p == null) continue;

        //            var v = has[key] == DBNull.Value ? "" : (has[key] ?? "");
        //            if (p.PropertyType == typeof(int)) p.SetValue(obj, v.toint32(0, true), null);
        //            if (p.PropertyType == typeof(DateTime)) p.SetValue(obj, v.todatetime("", true), null);
        //            if (p.PropertyType == typeof(decimal)) p.SetValue(obj, v.todecimal(0, true), null);
        //            if (p.PropertyType == typeof(string)) p.SetValue(obj, v, null);
        //        }
        //        catch { }
        //    }
        //    return (T)obj;
        //}

        /// <summary>
        /// 把第二个对象的数据加到第一个对象里面
        /// </summary>
        /// <param name="sm1"></param>
        /// <param name="sm2"></param>
        /// <returns></returns>
        public static supermodel operator +(supermodel sm1, supermodel sm2)
        {
            foreach (string key in sm2.Keys)
                sm1[key] = sm2[key];
            return sm1;
        }
        /// <summary>
        /// 把第二个对象的数据加到第一个对象里面
        /// </summary>
        /// <param name="sm1"></param>
        /// <param name="has"></param>
        /// <returns></returns>
        public static supermodel operator +(supermodel sm1, Hashtable has)
        {
            return sm1 + has;
        }

        /// <summary>
        /// 把对象的数据加到supermodel中
        /// </summary>
        /// <param name="sm1"></param>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static supermodel operator +(supermodel sm1, object obj)
        {
            return sm1 + supermodel.create().fromModel(obj);
        }

        /// <summary>
        /// 把supermodel给对象里面的属性，反射的效率非常低，可以考虑替换掉
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="sm1"></param>
        /// <returns></returns>
        public static object operator +(object obj, supermodel sm1)
        {
            var t = obj.GetType();
            foreach (string key in sm1.Keys)
            {
                try
                {
                    var p = t.GetProperty(key, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.IgnoreCase);
                    if (p == null) continue;

                    var v = sm1[key] == DBNull.Value ? "" : (sm1[key] ?? "");
                    if (p.PropertyType == typeof(int)) p.SetValue(obj, v.toint32(0, true), null);
                    if (p.PropertyType == typeof(DateTime)) p.SetValue(obj, v.todatetime("", true), null);
                    if (p.PropertyType == typeof(decimal)) p.SetValue(obj, v.todecimal(0, true), null);
                    if (p.PropertyType == typeof(string)) p.SetValue(obj, v, null);
                }
                catch { }
            }
            return obj;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        //public static implicit operator List<supermodel>(JavaScriptArray jsa)
        //{
        //    List<supermodel> sms = new List<supermodel>();
        //    foreach (JavaScriptObject jso in jsa)
        //    {
        //        supermodel sm = jso;
        //        sms.Add(sm);
        //    }

        //    return sms;
        //}
    }
}